package nancal.mp


import nancal.mp.db.mongo.mor
import nancal.mp.db.mongo.table.SysGroup
import nancal.mp.db.mysql.dbr
import nbcp.base.comm.JsonMap
import nbcp.base.db.IdName
import nbcp.base.enums.NameMappingTypeEnum
import nbcp.base.extend.AsString
import nbcp.base.extend.FullName
import nbcp.base.extend.resolvePath
import nbcp.base.utils.SpringUtil
import nbcp.base.utils.StringUtil
import nbcp.myoql.code.generator.db.mysql.SqlDbEntityGenerator
import nbcp.myoql.code.generator.tool.CrudCodeGeneratorUtil
import nbcp.myoql.db.comm.BaseMetaData
import nbcp.myoql.db.mongo.base.MongoColumnName
import nbcp.myoql.db.mongo.query
import nbcp.myoql.db.mongo.updateById
import nbcp.myoql.db.mongo.updateWithEntity
import org.bson.Document
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.io.File
import java.io.FileWriter


class tool : TestBase() {
    var workPath = System.getProperty("user.dir")

    var ents = JsonMap(
        "dev" to setOf(mor.dev.mongoConnection)
    )

    companion object {
        @BeforeEach
        fun before() {
            println("redis:" + SpringUtil.context.environment.getProperty("spring.data.redis.host"))
            println("mongo:" + SpringUtil.context.environment.getProperty("spring.data.mongo.uri"))
        }
    }


    /**
     * 根据表定义生成 建表语句
     */
    @Test
    fun entity2Sql() {
        var sqls = dbr.system.getEntities().map { table ->
            return@map SqlDbEntityGenerator.entity2Sql(table.systemDefineEntityType, NameMappingTypeEnum.UNDER_LINE)
        }

        println(sqls.joinToString("\n"))
    }

    @Test
    fun mongo_bk() {
        var m = SysGroup.AppMenuEntity("Copy_of_adminMenu")

        m.query()
            .toMapList()
            .map { root ->
                m.updateById(root.get("id").AsString())
                    .set { it.parent to IdName() }
                    .exec()

                (root.get("menus") as List<Document>).forEach {
                    it.put("parent", IdName(root.getString("id"), root.getString("name")))
                    it.put("menus", listOf<IdName>())
                    m.updateWithEntity(it).doubleExecSave()
                }
            }
    }

    @Test
    fun mongo_bk2() {
        var m = mor.sys.appMenu("mp-tenant-admin")

        m.query()
            .toMapList()
            .map { root ->
                m.updateById(root.get("id").AsString())
                    .set { MongoColumnName("menus") to listOf<IdName>() }
                    .exec()
            }
    }

    @Test
    fun gen_mongo_mvc() {
        JsonMap(
            "dev" to setOf(mor.dev.mongoConnection)
        ).forEach {
            var group = it.key;
            (it.value as Collection<BaseMetaData<Any>>).forEach {
                var entity = it;
                var entity_upper = StringUtil.getBigCamelCase(it.userDefineTableName)

                var fileNameAuto = File.separator + group + File.separator + entity_upper + "Controller.kt";
                write2File(
                    File(workPath).resolvePath("../../api/admin-api/src/main/kotlin/nancal/mp/mvc"),
                    fileNameAuto,
                    CrudCodeGeneratorUtil.genMongoMvcCrud(group, "nancal.mp", entity)
                )

            }
        }
    }


    @Test
    fun gen_vue_all() {
        this.gen_vue_list()
        this.gen_vue_card()

        this.gen_vue_router()
    }

    @Test
    fun gen_vue_card() {
        ents.forEach {
            var group = it.key;
            (it.value as Collection<BaseMetaData<Any>>).forEach {
                var entity = it;
                var entity_upper = StringUtil.getKebabCase(it.userDefineTableName)


                run {
                    var code = CrudCodeGeneratorUtil.genVue3Card(group, entity);

                    write2File(
                        File(workPath).resolvePath("../../api/admin-vue"),
                        File.separator + group + File.separator + entity_upper + "-card.vue",
                        code
                    )
                }
            }
        }
    }

    @Test
    fun gen_vue_list() {
        ents.forEach {
            var group = it.key;
            (it.value as Collection<BaseMetaData<Any>>).forEach {
                var entity = it;
                var entity_upper = StringUtil.getKebabCase(it.userDefineTableName)

                run {
                    var code = CrudCodeGeneratorUtil.genVue3List(group, entity);

                    write2File(
                        File(workPath).resolvePath("../../api/admin-vue"),
                        File.separator + group + File.separator + entity_upper + "-list.vue",
                        code
                    )
                }

            }
        }
    }

    @Test
    fun gen_vue_ref() {
        ents.forEach {
            var group = it.key;
            (it.value as Collection<BaseMetaData<Any>>).forEach {
                var entity = it;
                var entity_upper = StringUtil.getKebabCase(it.userDefineTableName)

                run {
                    var code = CrudCodeGeneratorUtil.genVue3Ref(group, entity);

                    write2File(
                        File(workPath).resolvePath("../../api/admin-vue"),
                        File.separator + group + File.separator + entity_upper + "-ref.vue",
                        code
                    )
                }
            }
        }
    }

    @Test
    fun gen_vue_router() {
        var list = mutableListOf<String>()

        ents.forEach {
            var group = it.key;


            (it.value as Collection<BaseMetaData<Any>>).forEach {
                var entity = it;
                var entity_upper = StringUtil.getBigCamelCase(entity.userDefineTableName)
                var url_name = StringUtil.getKebabCase(entity.userDefineTableName);

                if (url_name.startsWith(group + "-")) {
                    url_name = url_name.substring((group + "-").length);
                }


                list.add(
                    """
{
    path: '/${group}/${url_name}/list',
    component: resolve => require(['./view/${group}/${entity_upper}List.vue'], resolve)
},
{
    path: '/${group}/${url_name}/(add|edit)/:id',
    props:true,
    component: resolve => require(['./view/${group}/${entity_upper}Card.vue'], resolve)
},
{
    path: '/${group}/${url_name}/ref',
    component: resolve => require(['./view/${group}/${entity_upper}Ref.vue'], resolve)
},
"""
                )

            }
        }

        println("")
        println(list.joinToString(","))
    }


    private fun write2File(path: String, fileName: String, code: String) {
        var targetFile = File(path + fileName);
        if (path.isEmpty() || targetFile.exists()) {
            println("===================================================")
            println(fileName)
            println("----------------")
            println(code)
            println("===================================================")
            return;
        }

        if (targetFile.parentFile.exists() == false) {
            targetFile.parentFile.mkdirs();
        }

        var writer = FileWriter(targetFile.FullName)
        writer.write(code);
        writer.close();

        println(targetFile.FullName)
    }

}